const express = require("express");
const path = require("path");
const fs = require("fs").promises;
const os = require("os");
const multer = require("multer");
const compression = require("compression");
const favicon = require("serve-favicon");

const app = express();
const PORT = 3000;
const DOWNLOAD_DIR = path.join(__dirname, "downloads");

// 忽略 favicon 请求（添加此行）
app.get("/favicon.ico", (req, res) => res.status(204));
// 设置视图引擎
app.set("view engine", "ejs");
app.set("views", path.join(__dirname, "views"));

// 创建下载目录（如果不存在）
fs.mkdir(DOWNLOAD_DIR, { recursive: true }).catch((err) => {
  console.error("无法创建下载目录:", err);
});

// 配置Multer存储引擎
const storage = multer.diskStorage({
  destination: (req, file, cb) => {
    cb(null, DOWNLOAD_DIR);
  },
  filename: (req, file, cb) => {
    // 保留原始文件名
    cb(null, file.originalname);
  },
});

const upload = multer({
  storage: storage,
  limits: { fileSize: 1024 * 1024 * 1024 }, // 1GB文件大小限制
});

// 中间件
app.use(compression());
// app.use(favicon(path.join(__dirname, "public", "favicon.ico")));
app.use(express.static(path.join(__dirname, "public")));
app.use(express.urlencoded({ extended: true }));

// 设置视图引擎
app.set("view engine", "ejs");
app.set("views", path.join(__dirname, "views"));

// 获取所有网络接口的IP地址
function getIPAddresses() {
  const interfaces = os.networkInterfaces();
  const addresses = [];

  Object.keys(interfaces).forEach((ifname) => {
    interfaces[ifname].forEach((iface) => {
      if (iface.family === "IPv4" && !iface.internal) {
        addresses.push(iface.address);
      }
    });
  });

  return addresses;
}

// 格式化文件大小显示
function formatFileSize(bytes) {
  if (bytes === 0) return "0 Bytes";

  const k = 1024;
  const sizes = ["Bytes", "KB", "MB", "GB", "TB"];
  const i = Math.floor(Math.log(bytes) / Math.log(k));

  return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i];
}

// 首页 - 显示文件列表和上传表单
app.get("/", async (req, res) => {
  try {
    const files = await fs.readdir(DOWNLOAD_DIR);
    const fileDetails = await Promise.all(
      files.map(async (file) => {
        const filePath = path.join(DOWNLOAD_DIR, file);
        const stats = await fs.stat(filePath);

        return {
          name: file,
          size: formatFileSize(stats.size),
          mtime: stats.mtime.toLocaleString(),
          isDirectory: stats.isDirectory(),
        };
      })
    );

    // 按修改时间排序，最新的在前
    fileDetails.sort((a, b) => new Date(b.mtime) - new Date(a.mtime));

    res.render("index", { files: fileDetails });
  } catch (err) {
    console.error("读取文件列表错误:", err);
    res.status(500).send("无法获取文件列表");
  }
});

// 处理文件上传
app.post("/upload", upload.single("file"), (req, res) => {
  if (!req.file) {
    return res.status(400).send("未选择文件上传");
  }

  res.redirect("/");
});

// 处理文件下载
app.get("/download/:fileName", async (req, res) => {
  const fileName = req.params.fileName;
  const filePath = path.join(DOWNLOAD_DIR, fileName);

  try {
    await fs.access(filePath);
    res.download(filePath, fileName, (err) => {
      if (err) {
        console.error("下载错误:", err);
        res.status(500).send("下载失败");
      }
    });
  } catch (err) {
    console.error("文件不存在:", err);
    res.status(404).send("文件不存在");
  }
});

// 创建目录
app.post("/create-directory", async (req, res) => {
  const dirName = req.body.dirName;
  if (!dirName) {
    return res.status(400).send("目录名不能为空");
  }

  const dirPath = path.join(DOWNLOAD_DIR, dirName);

  try {
    await fs.mkdir(dirPath);
    res.redirect("/");
  } catch (err) {
    console.error("创建目录失败:", err);
    res.status(500).send("创建目录失败");
  }
});

// 启动服务器
const startServer = () => {
  const server = app.listen(PORT, () => {
    const host = "localhost";
    const ips = getIPAddresses();

    console.log(`文件服务器已启动！`);
    console.log(`本地访问地址：http://${host}:${PORT}`);

    if (ips.length > 0) {
      console.log(`局域网访问地址：`);
      ips.forEach((ip) => {
        console.log(`  http://${ip}:${PORT}`);
      });
    } else {
      console.log(`未检测到可用的网络IP地址。`);
    }

    console.log(`共享目录：${DOWNLOAD_DIR}`);
  });
};

startServer();
